package repository

import (
	"fmt"
	"time"

	"github.com/yourusername/rss-reader-ai/internal/model"
	"gorm.io/gorm"
)

// =====================================================
// ArticleRepository 接口定义
// =====================================================

// ArticleListFilter 文章列表过滤条件
type ArticleListFilter struct {
	FeedID    *int64     // 订阅源ID (可选)
	IsRead    *bool      // 是否已读 (可选)
	IsStarred *bool      // 是否收藏 (可选)
	Tags      []string   // 标签列表 (可选)
	Keyword   string     // 搜索关键词 (可选)
	StartDate *time.Time // 开始日期 (可选)
	EndDate   *time.Time // 结束日期 (可选)
	Limit     int        // 每页数量 (默认20)
	Offset    int        // 偏移量 (默认0)
}

// ArticleRepository 文章数据访问接口
type ArticleRepository interface {
	// Create 创建文章
	Create(article *model.Article) error

	// BatchCreate 批量创建文章(忽略重复)
	BatchCreate(articles []*model.Article) error

	// GetByID 根据ID获取文章(包含订阅源信息)
	GetByID(id int64) (*model.Article, error)

	// GetByGUID 根据FeedID和GUID获取文章
	GetByGUID(feedID int64, guid string) (*model.Article, error)

	// ExistsByFeedAndGUID 检查文章是否存在(根据 feed_id + guid)
	ExistsByFeedAndGUID(feedID int64, guid string) (bool, error)

	// List 获取文章列表(支持过滤和分页)
	List(filter *ArticleListFilter) ([]*model.Article, error)

	// ListByFeed 获取订阅源的文章列表
	ListByFeed(feedID int64, limit, offset int) ([]*model.Article, error)

	// ListUnread 获取未读文章列表
	ListUnread(limit, offset int) ([]*model.Article, error)

	// ListStarred 获取收藏文章列表
	ListStarred(limit, offset int) ([]*model.Article, error)

	// ListWithoutAISummary 获取未生成AI摘要的文章
	ListWithoutAISummary(limit int) ([]*model.Article, error)

	// Search 全文搜索文章
	Search(keyword string, limit, offset int) ([]*model.Article, error)

	// Update 更新文章
	Update(article *model.Article) error

	// UpdateFields 更新指定字段
	UpdateFields(id int64, fields map[string]interface{}) error

	// MarkRead 标记为已读
	MarkRead(id int64) error

	// MarkUnread 标记为未读
	MarkUnread(id int64) error

	// ToggleStar 切换收藏状态
	ToggleStar(id int64) error

	// Delete 删除文章
	Delete(id int64) error

	// DeleteByFeed 删除订阅源的所有文章
	DeleteByFeed(feedID int64) error

	// Count 统计文章数量
	Count(filter *ArticleListFilter) (int64, error)

	// CountUnread 统计未读文章数量
	CountUnread() (int64, error)

	// CountStarred 统计收藏文章数量
	CountStarred() (int64, error)
}

// =====================================================
// ArticleRepository 接口实现
// =====================================================

// articleRepository 文章数据访问实现
type articleRepository struct {
	db *gorm.DB
}

// NewArticleRepository 创建文章数据访问实例
func NewArticleRepository(db *gorm.DB) ArticleRepository {
	return &articleRepository{db: db}
}

// Create 创建文章
func (r *articleRepository) Create(article *model.Article) error {
	if article == nil {
		return fmt.Errorf("article不能为空")
	}
	return r.db.Create(article).Error
}

// BatchCreate 批量创建文章(忽略重复)
func (r *articleRepository) BatchCreate(articles []*model.Article) error {
	if len(articles) == 0 {
		return nil
	}
	
	// 使用事务批量插入,忽略重复的文章(违反唯一约束)
	return r.db.Transaction(func(tx *gorm.DB) error {
		for _, article := range articles {
			// 检查是否已存在
			var count int64
			tx.Model(&model.Article{}).
				Where("feed_id = ? AND guid = ?", article.FeedID, article.GUID).
				Count(&count)
			
			if count == 0 {
				if err := tx.Create(article).Error; err != nil {
					return err
				}
			}
		}
		return nil
	})
}

// GetByID 根据ID获取文章
func (r *articleRepository) GetByID(id int64) (*model.Article, error) {
	var article model.Article
	err := r.db.Preload("Feed").Preload("Tags").First(&article, id).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, fmt.Errorf("文章不存在: id=%d", id)
		}
		return nil, fmt.Errorf("查询文章失败: %w", err)
	}
	return &article, nil
}

// GetByGUID 根据FeedID和GUID获取文章
func (r *articleRepository) GetByGUID(feedID int64, guid string) (*model.Article, error) {
	var article model.Article
	err := r.db.Where("feed_id = ? AND guid = ?", feedID, guid).First(&article).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, nil // 不存在返回nil,不报错
		}
		return nil, fmt.Errorf("查询文章失败: %w", err)
	}
	return &article, nil
}

// ExistsByFeedAndGUID 检查文章是否存在(根据 feed_id + guid)
// 用于去重判断,比 GetByGUID 更高效
func (r *articleRepository) ExistsByFeedAndGUID(feedID int64, guid string) (bool, error) {
	var count int64
	err := r.db.Model(&model.Article{}).
		Where("feed_id = ? AND guid = ?", feedID, guid).
		Count(&count).Error
	
	if err != nil {
		return false, fmt.Errorf("检查文章是否存在失败: %w", err)
	}
	
	return count > 0, nil
}

// List 获取文章列表
func (r *articleRepository) List(filter *ArticleListFilter) ([]*model.Article, error) {
	if filter == nil {
		filter = &ArticleListFilter{}
	}
	
	// 设置默认值
	if filter.Limit <= 0 {
		filter.Limit = 20
	}
	if filter.Offset < 0 {
		filter.Offset = 0
	}
	
	query := r.db.Model(&model.Article{}).Preload("Feed")
	
	// 应用过滤条件
	query = r.applyFilter(query, filter)
	
	var articles []*model.Article
	err := query.Order("published_at DESC").
		Limit(filter.Limit).
		Offset(filter.Offset).
		Find(&articles).Error
	
	if err != nil {
		return nil, fmt.Errorf("查询文章列表失败: %w", err)
	}
	return articles, nil
}

// applyFilter 应用过滤条件
func (r *articleRepository) applyFilter(query *gorm.DB, filter *ArticleListFilter) *gorm.DB {
	if filter.FeedID != nil {
		query = query.Where("feed_id = ?", *filter.FeedID)
	}
	if filter.IsRead != nil {
		query = query.Where("is_read = ?", *filter.IsRead)
	}
	if filter.IsStarred != nil {
		query = query.Where("is_starred = ?", *filter.IsStarred)
	}
	if filter.Keyword != "" {
		// 使用 LIKE 搜索标题和摘要
		keyword := "%" + filter.Keyword + "%"
		query = query.Where("title LIKE ? OR description LIKE ? OR ai_summary LIKE ?",
			keyword, keyword, keyword)
	}
	if filter.StartDate != nil {
		query = query.Where("published_at >= ?", filter.StartDate)
	}
	if filter.EndDate != nil {
		query = query.Where("published_at <= ?", filter.EndDate)
	}
	return query
}

// ListByFeed 获取订阅源的文章列表
func (r *articleRepository) ListByFeed(feedID int64, limit, offset int) ([]*model.Article, error) {
	if limit <= 0 {
		limit = 20
	}
	
	var articles []*model.Article
	err := r.db.Where("feed_id = ?", feedID).
		Order("published_at DESC").
		Limit(limit).
		Offset(offset).
		Find(&articles).Error
	
	if err != nil {
		return nil, fmt.Errorf("查询订阅源文章失败: %w", err)
	}
	return articles, nil
}

// ListUnread 获取未读文章列表
func (r *articleRepository) ListUnread(limit, offset int) ([]*model.Article, error) {
	if limit <= 0 {
		limit = 20
	}
	
	var articles []*model.Article
	err := r.db.Preload("Feed").
		Where("is_read = ?", false).
		Order("published_at DESC").
		Limit(limit).
		Offset(offset).
		Find(&articles).Error
	
	if err != nil {
		return nil, fmt.Errorf("查询未读文章失败: %w", err)
	}
	return articles, nil
}

// ListStarred 获取收藏文章列表
func (r *articleRepository) ListStarred(limit, offset int) ([]*model.Article, error) {
	if limit <= 0 {
		limit = 20
	}
	
	var articles []*model.Article
	err := r.db.Preload("Feed").
		Where("is_starred = ?", true).
		Order("published_at DESC").
		Limit(limit).
		Offset(offset).
		Find(&articles).Error
	
	if err != nil {
		return nil, fmt.Errorf("查询收藏文章失败: %w", err)
	}
	return articles, nil
}

// ListWithoutAISummary 获取未生成AI摘要的文章
func (r *articleRepository) ListWithoutAISummary(limit int) ([]*model.Article, error) {
	if limit <= 0 {
		limit = 10
	}
	
	var articles []*model.Article
	err := r.db.Where("ai_summary IS NULL OR ai_summary = ''").
		Order("published_at DESC").
		Limit(limit).
		Find(&articles).Error
	
	if err != nil {
		return nil, fmt.Errorf("查询待生成摘要文章失败: %w", err)
	}
	return articles, nil
}

// Search 全文搜索文章
func (r *articleRepository) Search(keyword string, limit, offset int) ([]*model.Article, error) {
	if keyword == "" {
		return nil, fmt.Errorf("搜索关键词不能为空")
	}
	if limit <= 0 {
		limit = 20
	}
	
	var articles []*model.Article
	// 使用 MySQL 全文搜索
	err := r.db.Preload("Feed").
		Where("MATCH(title, description, content, ai_summary) AGAINST(? IN NATURAL LANGUAGE MODE)", keyword).
		Order("published_at DESC").
		Limit(limit).
		Offset(offset).
		Find(&articles).Error
	
	if err != nil {
		return nil, fmt.Errorf("搜索文章失败: %w", err)
	}
	return articles, nil
}

// Update 更新文章
func (r *articleRepository) Update(article *model.Article) error {
	if article == nil {
		return fmt.Errorf("article不能为空")
	}
	if article.ID == 0 {
		return fmt.Errorf("article ID不能为0")
	}
	return r.db.Save(article).Error
}

// UpdateFields 更新指定字段
func (r *articleRepository) UpdateFields(id int64, fields map[string]interface{}) error {
	if len(fields) == 0 {
		return fmt.Errorf("更新字段不能为空")
	}
	
	result := r.db.Model(&model.Article{}).
		Where("id = ?", id).
		Updates(fields)
	
	if result.Error != nil {
		return fmt.Errorf("更新文章字段失败: %w", result.Error)
	}
	if result.RowsAffected == 0 {
		return fmt.Errorf("文章不存在: id=%d", id)
	}
	return nil
}

// MarkRead 标记为已读
func (r *articleRepository) MarkRead(id int64) error {
	return r.UpdateFields(id, map[string]interface{}{"is_read": true})
}

// MarkUnread 标记为未读
func (r *articleRepository) MarkUnread(id int64) error {
	return r.UpdateFields(id, map[string]interface{}{"is_read": false})
}

// ToggleStar 切换收藏状态
func (r *articleRepository) ToggleStar(id int64) error {
	var article model.Article
	if err := r.db.First(&article, id).Error; err != nil {
		return fmt.Errorf("文章不存在: id=%d", id)
	}
	return r.UpdateFields(id, map[string]interface{}{"is_starred": !article.IsStarred})
}

// Delete 删除文章
func (r *articleRepository) Delete(id int64) error {
	result := r.db.Delete(&model.Article{}, id)
	if result.Error != nil {
		return fmt.Errorf("删除文章失败: %w", result.Error)
	}
	if result.RowsAffected == 0 {
		return fmt.Errorf("文章不存在: id=%d", id)
	}
	return nil
}

// DeleteByFeed 删除订阅源的所有文章
func (r *articleRepository) DeleteByFeed(feedID int64) error {
	return r.db.Where("feed_id = ?", feedID).Delete(&model.Article{}).Error
}

// Count 统计文章数量
func (r *articleRepository) Count(filter *ArticleListFilter) (int64, error) {
	if filter == nil {
		filter = &ArticleListFilter{}
	}
	
	query := r.db.Model(&model.Article{})
	query = r.applyFilter(query, filter)
	
	var count int64
	err := query.Count(&count).Error
	if err != nil {
		return 0, fmt.Errorf("统计文章数量失败: %w", err)
	}
	return count, nil
}

// CountUnread 统计未读文章数量
func (r *articleRepository) CountUnread() (int64, error) {
	var count int64
	err := r.db.Model(&model.Article{}).
		Where("is_read = ?", false).
		Count(&count).Error
	if err != nil {
		return 0, fmt.Errorf("统计未读文章数量失败: %w", err)
	}
	return count, nil
}

// CountStarred 统计收藏文章数量
func (r *articleRepository) CountStarred() (int64, error) {
	var count int64
	err := r.db.Model(&model.Article{}).
		Where("is_starred = ?", true).
		Count(&count).Error
	if err != nil {
		return 0, fmt.Errorf("统计收藏文章数量失败: %w", err)
	}
	return count, nil
}
